In most Unix style operating systems, when data is sent or received over a network, the data originates or terminates in user space accessible memory. When sending data, the data is generally copied from user space memory to a buffer space allocated to the kernel, and then eventually sent down the networking stack to a physical network device where, via a device driver, the data is sent via direct memory access (“DMA”). When receiving data, the hardware driver DMA's the data into a buffer space allocated to the kernel. An application, for example, a Server Message Block (“SMB”) server, can request that the data be copied from the buffer space allocated to the kernel to user space memory. Similarly, when a process wants to write data to disk, data residing in user space accessible memory can get copied to a page cache in the kernel, and eventually written to disk from the page cache.
In an operating system that supports multiple networking protocols, clients of those unique protocols expect data to be packaged according to the protocol specification. For example, if an SMB client and a Network File System (“NFS”) client both ask to read the same file, the data payload, e.g., the actual file data, will likely be the same when serving both requests. However, the protocol specifications, in general, require the data payload to be packaged with native protocol framing that can include metadata including checksum data or transformations to the data payload such as encrypted data payload or a compressed data payload. In one example, a checksum can be generated for each data payload and then be included in the message framing such that once the client receives the data payload and the checksum, the client can use the received data payload to independently compute its own checksum and then compare the computed checksum to the checksum received in the message framing to determine if any errors were introduced into the data payload during transmission.
Different protocols can, for example, use different checksum hash formulas, different encryption algorithms to protect data payloads, and different compression algorithms to compress data. In many of these scenarios, there is a requirement to make a computation on the data payload to generate at least a portion of the protocol message framing information. For example, it can require that the data payload be first transferred to user space accessible memory, then the user space native protocol head can make the necessary computations on the data payload to generate the proper message framing, and then the message framing and the data payload can be combined and copied to kernel space memory for eventual transfer to a client. Thus, every time a protocol head sends or receives data, it is likely necessary for the data to be copied twice, e.g., once from kernel space to user space and a second copy from user space back to kernel space. In large scale file systems, this can consume large amounts of computational and memory resources. It can be appreciated that zero-copy mechanisms can used to avoid copying data between user space and kernel space; however, they are not usable when a computation needs to be performed over the data. Thus, it can be appreciated that there exists a need for a zero-copy process that can provide for the necessary computation of protocol framing information without requiring a data payload to be copied to user space and then back to kernel space before being sent down the networking stack in the kernel for DMA to the network.